import re
import uuid
from io import BytesIO
import PyPDF2
from rest_framework import serializers, status
from rest_framework.response import Response
from rest_framework.views import APIView
from django.conf import settings
from datetime import datetime
from wsgiref.handlers import format_date_time
from time import mktime
import hashlib
import base64
import hmac
from urllib.parse import urlencode
import json
import requests
import docx
from Resume.models import Resume
from Resume.service.API import extract_parsedData_info_ws
from Resume.service.utils import upload_to_oss


class AssembleHeaderException(Exception):
    """自定义鉴权头异常"""

    def __init__(self, msg):
        self.message = msg


class ResumeSerializer(serializers.Serializer):
    text = serializers.CharField(
        required=True,
        min_length=50,  # 添加最小长度限制
        max_length=5000,
        label="简历文本",
        help_text="需要生成简历的原始文本内容（建议包含姓名、教育经历、工作经历等关键信息）"
    )


class GetResumeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Resume
        fields = ['resume_id','content', 'parsed_data', 'resume_path', 'upload_time']


class XFResumeAPIView(APIView):
    """
    API视图：处理简历生成请求

    POST参数：
    - text: 需要生成简历的原始文本

    返回：
    - 包含简历链接的JSON响应
    """

    class Url:
        """URL解析辅助类"""

        def __init__(self, host, path, schema):
            self.host = host
            self.path = path
            self.schema = schema

    def _sha256base64(self, data):
        """计算SHA256并Base64编码"""
        sha256 = hashlib.sha256()
        sha256.update(data)
        return base64.b64encode(sha256.digest()).decode('utf-8')

    def _parse_url(self, request_url):
        """解析URL"""
        stidx = request_url.index("://")
        host = request_url[stidx + 3:]
        schema = request_url[:stidx + 3]
        edidx = host.index("/")
        if edidx <= 0:
            raise AssembleHeaderException(f"无效请求URL: {request_url}")
        return self.Url(host[:edidx], host[edidx:], schema)

    def _assemble_ws_auth_url(self, request_url, method="GET"):
        """生成鉴权URL"""
        u = self._parse_url(request_url)
        now = datetime.now()
        date = format_date_time(mktime(now.timetuple()))

        signature_origin = f"host: {u.host}\ndate: {date}\n{method} {u.path} HTTP/1.1"
        signature_sha = hmac.new(
            settings.XF_API_SECRET.encode('utf-8'),
            signature_origin.encode('utf-8'),
            digestmod=hashlib.sha256
        ).digest()

        signature_b64 = base64.b64encode(signature_sha).decode('utf-8')
        auth_origin = f'api_key="{settings.XF_API_KEY}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature_b64}"'
        authorization = base64.b64encode(auth_origin.encode('utf-8')).decode('utf-8')

        return f"{request_url}?{urlencode({'host': u.host, 'date': date, 'authorization': authorization})}"

    def _get_request_body(self, text):
        """构建请求体"""
        return {
            "header": {"app_id": settings.XF_APPID, "status": 3},
            "parameter": {
                "ai_resume": {
                    "resData": {"encoding": "utf8", "compress": "raw", "format": "json"}
                }
            },
            "payload": {
                "reqData": {
                    "encoding": "utf8",
                    "compress": "raw",
                    "format": "plain",
                    "status": 3,
                    "text": base64.b64encode(text.encode("utf-8")).decode('utf-8')
                }
            }
        }

    def post(self, request):
        """处理POST请求"""
        serializer = ResumeSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        try:
            # 获取配置
            host = getattr(settings, 'XF_RESUME_API_HOST', 'https://cn-huadong-1.xf-yun.com/v1/private/s73f4add9')

            # 生成鉴权URL
            auth_url = self._assemble_ws_auth_url(
                host,
                method='POST',
            )

            # 发送请求
            response = requests.post(
                auth_url,
                json=self._get_request_body(serializer.validated_data['text']),
                headers={'Content-Type': 'application/json'}
            )

            # 处理响应
            if response.status_code != 200:
                raise Exception(f"API请求失败，状态码：{response.status_code}，响应内容：{response.text}")

            response_data = response.json()
            print("完整API响应：", json.dumps(response_data, indent=2))  # 添加调试日志

            # 检查业务状态码
            if response_data['header']['code'] != 0:
                return Response({
                    "error": "简历生成失败",
                    "code": response_data['header']['code'],
                    "message": response_data['header']['message']
                }, status=status.HTTP_400_BAD_REQUEST)

            # 解码并处理数据
            try:
                encoded_text = response_data['payload']['resData']['text']
                resume_text = base64.b64decode(encoded_text).decode('utf-8')
                resume_data = json.loads(resume_text)

                # 检查是否存在links字段
                if 'links' not in resume_data or not isinstance(resume_data['links'], list):
                    return Response({
                        "error": "响应数据结构异常",
                        "detail": "缺少有效的简历链接列表",
                        "raw_data": resume_data
                    }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

                # 提取所有可用链接
                links = [
                    {
                        "img_url": item.get('img_url'),
                        "word_url": item.get('word_url')
                    }
                    for item in resume_data['links']
                ]

                # 可以选择返回第一个有效链接或全部链接
                if not any(links):
                    return Response({
                        "error": "未找到有效简历链接",
                        "raw_data": resume_data
                    }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

                return Response({
                    "status": "success",
                    "links": links
                })
            except json.JSONDecodeError as e:
                return Response({
                    "error": "响应数据解析失败",
                    "raw_content": resume_text
                }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            except KeyError as e:
                return Response({
                    "error": "接口响应结构异常",
                    "missing_key": str(e),
                    "response_data": response_data
                }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        except AssembleHeaderException as e:
            return Response({"error": f"鉴权失败: {e.message}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


# 解析简历
class UploadResumeView(APIView):
    def parse_pdf(self, file_content):
        """解析PDF简历"""
        # 使用BytesIO处理二进制内容
        pdf_reader = PyPDF2.PdfReader(BytesIO(file_content))
        text = "\n".join([page.extract_text() for page in pdf_reader.pages])
        # 替换连续2个及以上的\n为单个\n
        cleaned_text = re.sub(r'\n{2,}', '\n', text)
        # 提取结构化数据
        structured_data = extract_parsedData_info_ws(cleaned_text)
        return cleaned_text, structured_data

    def parse_word(self, file_content):
        """解析Word简历"""
        doc = docx.Document(file_content)
        text = "\n".join([para.text for para in doc.paragraphs])
        # 替换连续2个及以上的\n为单个\n
        cleaned_text = re.sub(r'\n{2,}', '\n', text)
        structured_data = extract_parsedData_info_ws(cleaned_text)
        return cleaned_text, structured_data

    def post(self, request):
        user_id = request.user.get('user_id')
        if 'resume' not in request.FILES:
            return Response({'error': '请上传简历文件'}, status=400)
        uploaded_file = request.FILES['resume']
        #  生成一个 OSS 路径，并上传文件
        ext = uploaded_file.name.rsplit('.', 1)[-1]
        oss_path = f"resume/{user_id}/{uuid.uuid4().hex}.{ext}"
        oss_url = upload_to_oss(uploaded_file, oss_path)
        if not oss_url:
            return Response(
                {"error": "OSS 上传失败"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
        file_ext = uploaded_file.name.split('.')[-1].lower()
        # 直接读取文件内容到内存
        file_content = b''.join([chunk for chunk in uploaded_file.chunks()])
        try:
            # 根据文件类型调用不同解析方法
            if file_ext == 'pdf':
                content, parsed_data = self.parse_pdf(file_content)
            elif file_ext in ['doc', 'docx']:
                content, parsed_data = self.parse_word(uploaded_file)
            else:
                return Response({'error': '不支持该格式文件，请上传pdf或者word格式文件'}, status=400)
            # 创建简历记录
            resume = Resume.objects.create(
                user_id=user_id,
                content=content,
                parsed_data=parsed_data,
                resume_path=oss_url
            )
            return Response({
                'code': 200,
                'msg': 'success',
                'data': {
                    'resume_id': resume.resume_id,
                    'content_length': len(content),
                    'content': content,
                    'parsed_data': parsed_data,
                    'resume_path': oss_url
                }
            })
        except Exception as e:
            return Response({'error': str(e)}, status=500)


class getResumeView(APIView):
    def post(self, request):
        user_id = request.user.get('user_id')
        resume = Resume.objects.filter(user_id=user_id).all()
        serializer = GetResumeSerializer(instance=resume, many=True)
        return Response({
            'code': 200,
            'msg': 'success',
            'data': serializer.data
        })


